/*******************************************************************************
 * @file fdt_channel.h
 * @brief  inter process Fast Data Transfer
 *
 *
 * Author: Kevinx
 *
 * Copyright (c) 2015 Kevinx. All Rights Reserved.
 *
 * CONFIDENTIALITY AND LIMITED USE
 *
 * This software, including any software of third parties embodied herein,
 * contains information and concepts which are confidential to Kevinx
 * and such third parties. This software is licensed for use
 * solely in accordance with the terms and conditions of the applicable
 * license agreement with Kevinx or its authorized distributor.
 ************************************************************************************/
#ifndef __FDT_CHANNEL_H__
#define __FDT_CHANNEL_H__
#include <time.h>
#include <sys/types.h>
#include "fdt_shmmgr.h"
#ifdef FDT_DEBUG
#include <sys/syscall.h>
#define gettid() syscall(__NR_gettid)
#endif

struct cid_t {
    const char* cid;
    const char* peerid;
    unsigned int size;
    
};

struct fdt_channel;
struct fdt_channel_operations {
    int (*open)(struct fdt_channel*, struct cid_t*, int);
    void (*close)(struct fdt_channel*);
    int (*send)(struct fdt_channel*, const void*, int);
    int (*receive)(struct fdt_channel*, void*, int);
    int (*poll)(struct fdt_channel*, struct timeval*);
};

struct fdt_callback
{
    int (*func)(struct fdt_channel*);
};

#define FCH_TYPE_PTR   0x1000
#define FCH_NO_NEED_GR 0x0001
#define FCH_NO_NEED_GC 0x0002 
#define FCH_NO_RESTART 0x0004
#define FCH_PRIMARY    0x0008

struct fdt_channel {
    int* ifd;
    int* ofd;
    int* gc_fd;
    int* gr_fd;
    
    int pfds[2];/* PTR: 0 -- data transfer, 1 - garbage collection */
    int sfds[2];/* MSG: 0 - primary, 1 - secondary */

    struct list_head list;

    /*struct list_head shma_list;
    struct shm_area_struct* shma_cache;*/
    struct shm_area_struct* ref_shma;

    int flags;

    struct fdt_shmmgr* shmmgr;

    struct fdt_channel_operations* ops;
    struct fdt_callback* cb;
};

#define get_ingress_fd(fch) (*(fch)->ifd)
#define get_gc_fd(fch) (*(fch)->gc_fd)
#define get_egress_fd(fch) (*(fch)->ofd)
#define get_gr_fd(fch) (*(fch)->gr_fd)

/*
 * make_primary_PTR_channel
 * make_primary_PTR_channel:
 *    make PTR channel. the two end in communication must be one is primary and the other is secondary
 *
 * @return: 0 - success, -1 - failed
 */
int make_primary_PTR_channel(struct fdt_channel* c, struct fdt_shmmgr* shmmgr);
int make_secondary_PTR_channel(struct fdt_channel* c, struct fdt_shmmgr* shmmgr);

/*
 * make_primary_MSG_channel
 * make_secondary_MSG_channel
 *  make MSG channel. the two end in communication must be one is primary and the other is secondary
 *
 * @return: 0 - success, -1 - failed
 */
int make_primary_MSG_channel(struct fdt_channel* c);
int make_secondary_MSG_channel(struct fdt_channel* c);

/*
 * fdt_PTR_channel:
 *   test if c is a PTR channel
 *
 */
//int fdt_PTR_channel(struct fdt_channel* c);

/*
 * fdt_channel_open:
 *
 * @return: 0 - success, -1 - failed
 */
int fdt_channel_open(struct fdt_channel* c, struct cid_t* id, int flags);

/*
 * fdt_channel_close
 *
 */
void fdt_channel_close(struct fdt_channel* c);

/*
 * fdt_channel_send:
 *  for MSG channel, last two args should be the msg content and it's len.
 *  for PTR channel, "buf" arg are the pointer/len pairs refer to shared memory. len gives the number of pair(len/sizeof(BP)).
 *
 *  @return: number of bytes to send - sucess, 0 - nothing sent, -1 - sending failed
 */
int fdt_channel_send(struct fdt_channel* c, const void* buf, int size);

/*
 * fdt_channel_receive:
 *  for MSG channel, last two args are the msg content and it's len.
 *  for PTR channel, "buf" arg will be the pointer/len pairs refer to shared memory. return value gives the number of pair received.
 *
 * @return: number of bytes received - success; -1 - receive failed
 */
int fdt_channel_receive(struct fdt_channel* c, void* buf, int size);

/*
 * fdt_channel_poll: 
 *  polling if there is data to read
 *
 * @return: positive - sucess, 0 - time out, -1 - polling failed
 */
int fdt_channel_poll(struct fdt_channel* c, struct timeval* tv);

/*
 * fdt_PTRch_gcollect
 *  collect garbage for garbage channel
 *
 * @return: 0 - sucess, -1 - failed
 */
int fdt_PTRch_gcollect(struct fdt_channel* c);

/*
 * fdt_PTRch_GC_poll: 
 *  polling if there is garbage in channel to collect
 *
 * @return: positive - sucess, 0 - time out, -1 - polling failed
 */
int fdt_PTRch_GC_poll(struct fdt_channel* c, struct timeval* tv);

/*
 * fdt_PTRch_greturn:
 *  return garbarg to peer
 * @return: 0 - sucess, -1 - failed
 */
int fdt_PTRch_greturn(struct fdt_channel* c, const void* buf, int size);

#endif /* __FDT_CHANNEL_H__ */
